{
 "metadata": {
  "signature": "sha256:79cc3cf6926758692befe44fb35be1ab903a035d56fccb8e8c73670b0a4d3e6d"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Pyrex And NumPy\n",
      "===============\n",
      "\n",
      "Please note that the code described here is slightly out of date, since\n",
      "today [cython](http://cython.org) is the actively maintained version of\n",
      "Pyrex, and numpy now ships with Cython examples.\n",
      "\n",
      "Rather than maintaining both the wiki and the source dir, we'll continue\n",
      "to update the sources, kept\n",
      "[here](http://projects.scipy.org/scipy/numpy/browser/trunk/numpy/doc/cython).\n",
      "\n",
      "Old Pyrex page\n",
      "--------------\n",
      "\n",
      "[Pyrex](http://nz.cosc.canterbury.ac.nz/~greg/python/Pyrex/) is a\n",
      "language for writing C extensions to Python. Its syntax is very similar\n",
      "to writing Python. A file is compiled to a file, which is then compiled\n",
      "like a standard C extension module for Python. Many people find writing\n",
      "extension modules with Pyrex preferable to writing them in C or using\n",
      "other tools, such as SWIG.\n",
      "\n",
      "This page is a starting point for accessing numpy arrays natively with\n",
      "Pyrex. Please note that with current versions of NumPy (SVN), the\n",
      "directory contains a complete working example with the code in this\n",
      "page, including also a proper file so you can install it with the\n",
      "standard Python mechanisms. This should help you get up and running\n",
      "quickly.\n",
      "\n",
      "Here's a file I call \"c\\_python.pxd\":"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "cdef extern from \"Python.h\":\n",
      "    ctypedef int Py_intptr_t"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "and here's \"c\\_numpy.pxd\":"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "cimport c_python\n",
      "\n",
      "cdef extern from \"numpy/arrayobject.h\":\n",
      "    ctypedef class numpy.ndarray [object PyArrayObject]:\n",
      "        cdef char *data\n",
      "        cdef int nd\n",
      "        cdef c_python.Py_intptr_t *dimensions\n",
      "        cdef c_python.Py_intptr_t *strides\n",
      "        cdef object base\n",
      "        # descr not implemented yet here...\n",
      "        cdef int flags\n",
      "        cdef int itemsize\n",
      "        cdef object weakreflist\n",
      "\n",
      "    cdef void import_array()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Here's an example program, name this something like \"test.pyx\" suffix."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "cimport c_numpy\n",
      "cimport c_python\n",
      "import numpy\n",
      "\n",
      "c_numpy.import_array()\n",
      "\n",
      "def print_array_info(c_numpy.ndarray arr):\n",
      "    cdef int i\n",
      "\n",
      "    print '-='*10\n",
      "    print 'printing array info for ndarray at 0x%0lx'%(<c_python.Py_intptr_t>arr,)\n",
      "    print 'print number of dimensions:',arr.nd\n",
      "    print 'address of strides: 0x%0lx'%(<c_python.Py_intptr_t>arr.strides,)\n",
      "    print 'strides:'\n",
      "    for i from 0<=i<arr.nd:\n",
      "        # print each stride\n",
      "        print '  stride %d:'%i,<c_python.Py_intptr_t>arr.strides[i]\n",
      "    print 'memory dump:'\n",
      "    print_elements( arr.data, arr.strides, arr.dimensions, arr.nd, sizeof(double), arr.dtype )\n",
      "    print '-='*10\n",
      "    print\n",
      "    \n",
      "cdef print_elements(char *data,\n",
      "                    c_python.Py_intptr_t* strides,\n",
      "                    c_python.Py_intptr_t* dimensions,\n",
      "                    int nd,\n",
      "                    int elsize,\n",
      "                    object dtype):\n",
      "    cdef c_python.Py_intptr_t i,j\n",
      "    cdef void* elptr\n",
      "    \n",
      "    if dtype not in [numpy.dtype(numpy.object_),\n",
      "                     numpy.dtype(numpy.float64)]:\n",
      "        print '   print_elements() not (yet) implemented for dtype %s'%dtype.name\n",
      "        return\n",
      "    \n",
      "    if nd ==0:\n",
      "        if dtype==numpy.dtype(numpy.object_):\n",
      "            elptr = (<void**>data)[0] #[0] dereferences pointer in Pyrex\n",
      "            print '  ',<object>elptr\n",
      "        elif dtype==numpy.dtype(numpy.float64):\n",
      "            print '  ',(<double*>data)[0]\n",
      "    elif nd == 1:\n",
      "        for i from 0<=i<dimensions[0]:\n",
      "            if dtype==numpy.dtype(numpy.object_):\n",
      "                elptr = (<void**>data)[0]\n",
      "                print '  ',<object>elptr\n",
      "            elif dtype==numpy.dtype(numpy.float64):\n",
      "                print '  ',(<double*>data)[0]\n",
      "            data = data + strides[0]\n",
      "    else:\n",
      "        for i from 0<=i<dimensions[0]:\n",
      "            print_elements(data, strides+1, dimensions+1, nd-1, elsize, dtype)\n",
      "            data = data + strides[0]\n",
      "\n",
      "def test():\n",
      "    \"\"\"this function is pure Python\"\"\"\n",
      "    arr1 = numpy.array(-1e-30,dtype=numpy.Float64)\n",
      "    arr2 = numpy.array([1.0,2.0,3.0],dtype=numpy.Float64)\n",
      "\n",
      "    arr3 = numpy.arange(9,dtype=numpy.Float64)\n",
      "    arr3.shape = 3,3\n",
      "\n",
      "    four = 4\n",
      "    arr4 = numpy.array(['one','two',3,four],dtype=numpy.object_)\n",
      "\n",
      "    arr5 = numpy.array([1,2,3]) # int types not (yet) supported by print_elements\n",
      "\n",
      "    for arr in [arr1,arr2,arr3,arr4,arr5]:\n",
      "        print_array_info(arr)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Now, if you compile and install the above test.pyx, the output of should\n",
      "be something like the following:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "-=-=-=-=-=-=-=-=-=-=\n",
      "printing array info for ndarray at 0x8184508\n",
      "print number of dimensions: 0\n",
      "address of strides: 0xb764f7ec\n",
      "strides:\n",
      "memory dump:\n",
      "   -1e-30\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "printing array info for ndarray at 0x8190060\n",
      "print number of dimensions: 1\n",
      "address of strides: 0x818453c\n",
      "strides:\n",
      "  stride 0: 8\n",
      "memory dump:\n",
      "   1.0\n",
      "   2.0\n",
      "   3.0\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "printing array info for ndarray at 0x82698a0\n",
      "print number of dimensions: 2\n",
      "address of strides: 0x8190098\n",
      "strides:\n",
      "  stride 0: 24\n",
      "  stride 1: 8\n",
      "memory dump:\n",
      "   0.0\n",
      "   1.0\n",
      "   2.0\n",
      "   3.0\n",
      "   4.0\n",
      "   5.0\n",
      "   6.0\n",
      "   7.0\n",
      "   8.0\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "printing array info for ndarray at 0x821d6e0\n",
      "print number of dimensions: 1\n",
      "address of strides: 0x818ed74\n",
      "strides:\n",
      "  stride 0: 4\n",
      "memory dump:\n",
      "   one\n",
      "   two\n",
      "   3\n",
      "   4\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "\n",
      "-=-=-=-=-=-=-=-=-=-=\n",
      "printing array info for ndarray at 0x821d728\n",
      "print number of dimensions: 1\n",
      "address of strides: 0x821d75c\n",
      "strides:\n",
      "  stride 0: 4\n",
      "memory dump:\n",
      "   print_elements() not (yet) implemented for dtype int32\n",
      "-=-=-=-=-=-=-=-=-=-="
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "\n",
      "The [http://pytables.sourceforge.net/ pytables project] makes extensive use of Pyrex and numarray. See the pytables source code for more ideas.\n",
      "\n",
      "= See Also =\n",
      " [\"Cookbook/ArrayStruct_and_Pyrex\"]"
     ]
    }
   ],
   "metadata": {}
  }
 ]
}